use crate::REQWEST_CLIENT;
use anyhow::Result;
use serde::{ Deserialize, Serialize };
use serde_json::Value;

/// https://data.eastmoney.com/gdfx/ShareHolderDetail.html?hdCode=70010111
///
/// Mapping to [RPT_F10_EH_FREEHOLDERS.json](file:///Users/CC/gitee/conanchen/fuquants-workspace/crates/fudacli/eastmoney/sample/RPT_F10_EH_FREEHOLDERS.json)
#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10EhFreeholders {
    pub version: Value,
    pub result: RptF10EhFreeholdersResult,
    pub success: Value,
    pub message: Value,
    pub code: Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10EhFreeholdersResult {
    pub pages: Value,
    pub data: Vec<RptF10EhFreeholdersResultData>,
    pub count: Option<Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RptF10EhFreeholdersResultData {
    #[serde(rename = "SECUCODE")] // 证券代码
    pub secucode: Option<Value>,

    #[serde(rename = "SECURITY_CODE")] // 证券代码
    pub security_code: Option<Value>,

    #[serde(rename = "ORG_CODE")] // 组织代码
    pub org_code: Option<Value>,

    #[serde(rename = "END_DATE")] // 结束日期
    pub end_date: Option<Value>,

    #[serde(rename = "HOLDER_NAME")] // 持有人名称
    pub holder_name: Option<Value>,

    #[serde(rename = "HOLD_NUM")] // 持有数量
    pub hold_num: Option<Value>,

    #[serde(rename = "FREE_HOLDNUM_RATIO")] // 自由流通股比例
    pub free_holdnum_ratio: Option<Value>,

    #[serde(rename = "HOLD_NUM_CHANGE")] // 持股数量变动情况
    pub hold_num_change: Option<Value>,

    #[serde(rename = "CHANGE_RATIO")] // 持股比例变动
    pub change_ratio: Option<Value>,

    #[serde(rename = "IS_HOLDORG")] // 是否为持股机构标识
    pub is_holdorg: Option<Value>,

    #[serde(rename = "HOLDER_RANK")] // 持股排名
    pub holder_rank: Option<Value>,

    #[serde(rename = "SECURITY_NAME_ABBR")] // 证券简称
    pub security_name_abbr: Option<Value>,

    #[serde(rename = "HOLDER_CODE")] // 持有人代码
    pub holder_code: Option<Value>,

    #[serde(rename = "SECURITY_TYPE_CODE")] // 证券类型代码
    pub security_type_code: Option<Value>,

    #[serde(rename = "HOLDER_STATE")] // 持股状态
    pub holder_state: Option<Value>,

    #[serde(rename = "HOLDER_MARKET_CAP")] // 持股市值
    pub holder_market_cap: Option<Value>,

    #[serde(rename = "HOLD_RATIO")] // 持股比例
    pub hold_ratio: Option<Value>,

    #[serde(rename = "HOLD_CHANGE")] // 持股变动情况描述
    pub hold_change: Option<Value>,

    #[serde(rename = "HOLD_RATIO_CHANGE")] // 持股比例变动描述
    pub hold_ratio_change: Option<Value>,

    #[serde(rename = "HOLDER_TYPE")] // 持有人类型
    pub holder_type: Option<Value>,

    #[serde(rename = "SHARES_TYPE")] // 股份类型
    pub shares_type: Option<Value>,

    #[serde(rename = "UPDATE_DATE")] // 更新日期
    pub update_date: Option<Value>,

    #[serde(rename = "REPORT_DATE_NAME")] // 报告期名称
    pub report_date_name: Option<Value>,

    #[serde(rename = "HOLDER_NEW")] // 新的持有人代码或标识
    pub holder_new: Option<Value>,

    #[serde(rename = "FREE_RATIO_QOQ")] // 季度间自由流通股比例变动
    pub free_ratio_qoq: Option<Value>,

    #[serde(rename = "HOLDER_STATEE")] // 持股状态（可能重复字段）
    pub holder_statee: Option<Value>,

    #[serde(rename = "IS_REPORT")] // 是否为报告数据标识
    pub is_report: Option<Value>,

    #[serde(rename = "HOLDER_CODE_OLD")] // 旧的持有人代码
    pub holder_code_old: Option<Value>,

    #[serde(rename = "HOLDER_NEWTYPE")] // 持有人新类型标识
    pub holder_newtype: Option<Value>,

    #[serde(rename = "HOLDNUM_CHANGE_NAME")] // 持股数量变动的具体描述
    pub holdnum_change_name: Option<Value>,

    #[serde(rename = "IS_MAX_REPORTDATE")] // 是否为最近年报标识
    pub is_max_reportdate: Option<Value>,

    #[serde(rename = "COOPERATION_HOLDER_MARK")] // 合作持股标识
    pub cooperation_holder_mark: Option<Value>,

    #[serde(rename = "MXID")] // 不明标识符
    pub mxid: Option<Value>,

    #[serde(rename = "LISTING_STATE")] // 上市状态
    pub listing_state: Option<Value>,

    #[serde(rename = "XZCHANGE")] // 变动详情
    pub xzchange: Option<Value>,

    #[serde(rename = "NEW_CHANGE_RATIO")] // 新的持股比例变动描述
    pub new_change_ratio: Option<Value>,

    #[serde(rename = "HOLDER_STATE_NEW")] // 更新的持股状态
    pub holder_state_new: Option<Value>,

    #[serde(rename = "HOLD_ORG_CODE_SOURCE")] // 持股机构代码来源
    pub hold_org_code_source: Option<Value>,
}
/// Referer: https://data.eastmoney.com/gdfx/ShareHolderDetail.html?hdCode=70010111
///
/// pn: u16 page-number start from 1,
///
/// pz: u16 page-size e.g. 20
///
pub async fn rpt_f10_eh_freeholders(pn: u16, pz: u16) -> Result<RptF10EhFreeholders> {
    // Query String Parameters:
    //
    // callback: jQuery112308453423570988037_1716002480811
    // sortColumns: UPDATE_DATE,END_DATE,SECURITY_CODE
    // sortTypes: -1,-1,-1
    // pageSize: 50
    // pageNumber: 3
    // columns: ALL
    // source: WEB
    // client: WEB
    // filter: (HOLDER_NEW="70010111")(END_DATE>='2015-03-31')
    // reportName: RPT_F10_EH_FREEHOLDERS

    let request_url = format!(
        "https://datacenter-web.eastmoney.com/api/data/v1/get?sortColumns=UPDATE_DATE%2CEND_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1%2C-1&pageSize=50&pageNumber=3&columns=ALL&source=WEB&client=WEB&filter=(HOLDER_NEW%3D%2270010111%22)(END_DATE%3E%3D%272015-03-31%27)&reportName=RPT_F10_EH_FREEHOLDERS"
    );

    // Host: datacenter-web.eastmoney.com
    // Pragma: no-cache
    // Referer: https://data.eastmoney.com/gdfx/ShareHolderDetail.html?hdCode=70010111

    let response = REQWEST_CLIENT.get(request_url)
        .header(reqwest::header::ACCEPT, "*/*")
        .header(reqwest::header::ACCEPT_ENCODING, "gzip, deflate, br")
        .header(reqwest::header::ACCEPT_LANGUAGE, "zh-CN,zh;q=0.9,en;q=0.8")
        .header(reqwest::header::CACHE_CONTROL, "no-cache")
        .header(reqwest::header::CONNECTION, "keep-alive")
        // .header(COOKIE, "qgqp_b_id=d6299473145338f68687834ba37fa719; st_si=77687174285423; AUTH_FUND.EASTMONEY.COM_GSJZ=AUTH*TTJJ*TOKEN; EMFUND0=01-16%2016%3A57%3A06@%23%24%u4E2D%u822A%u65B0%u8D77%u822A%u7075%u6D3B%u914D%u7F6E%u6DF7%u5408A@%23%24005537; EMFUND1=01-16%2017%3A04%3A53@%23%24%u91D1%u4FE1%u6D88%u8D39%u5347%u7EA7%u80A1%u7968A@%23%24006692; EMFUND2=01-16%2020%3A01%3A56@%23%24%u5357%u65B9%u4E0A%u8BC1380ETF@%23%24510290; EMFUND3=01-29%2015%3A02%3A07@%23%24%u534E%u590F%u4E2D%u8BC1%u5168%u6307%u623F%u5730%u4EA7ETF@%23%24515060; EMFUND4=01-30%2014%3A41%3A22@%23%24%u534E%u6CF0%u67CF%u745E%u6D88%u8D39%u6210%u957F%u6DF7%u5408@%23%24001069; EMFUND5=01-30%2014%3A45%3A59@%23%24%u5E7F%u53D1%u6052%u751F%u6D88%u8D39%28QDII-ETF%29@%23%24159699; EMFUND6=01-30%2014%3A47%3A24@%23%24%u5357%u65B9%u7EA2%u5229%u4F4E%u6CE250ETF@%23%24515450; EMFUND7=01-31%2015%3A21%3A23@%23%24%u56FD%u8054%u4E2D%u8BC1%u7164%u70AD%u6307%u6570%28LOF%29A@%23%24168204; EMFUND8=02-02%2008%3A34%3A56@%23%24%u666F%u987A%u957F%u57CE%u652F%u67F1%u4EA7%u4E1A%u6DF7%u5408@%23%24260117; EMFUND9=02-02 10:30:22@#$%u897F%u90E8%u5229%u5F97%u805A%u79BE%u6DF7%u5408A@%23%24007423; st_asi=delete; HAList=ty-1-513130-%u6052%u751F%u79D1%u6280ETF%2Cty-0-300078-%u601D%u521B%u533B%u60E0%2Cty-0-300486-%u4E1C%u6770%u667A%u80FD%2Cty-1-513360-%u6559%u80B2ETF%2Cty-0-300478-%u676D%u5DDE%u9AD8%u65B0%2Cty-0-301589-N%u8BFA%u74E6%2Cty-1-603135-%u4E2D%u91CD%u79D1%u6280%2Cty-0-000001-%u5E73%u5B89%u94F6%u884C%2Cty-0-002400-%u7701%u5E7F%u96C6%u56E2%2Cty-1-601127-%u8D5B%u529B%u65AF; st_pvi=47260449691882; st_sp=2024-01-12%2017%3A28%3A27; st_inirUrl=https%3A%2F%2Fwww.google.com.hk%2F; st_sn=438; st_psi=20240226102321941-113200301321-9024721593")
        .header(reqwest::header::HOST, "datacenter-web.eastmoney.com")
        .header(reqwest::header::PRAGMA, "no-cache")
        .header(
            reqwest::header::REFERER,
            "https://data.eastmoney.com/gdfx/ShareHolderDetail.html?hdCode=70010111"
        )
        .header(
            reqwest::header::USER_AGENT,
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
        )
        .header(
            "Sec-Ch-Ua",
            "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\""
        )
        .header("Sec-Ch-Ua-Mobile", "?0")
        .header("Sec-Ch-Ua-Platform", "\"macOS\"")
        .header("Sec-Fetch-Dest", "empty")
        .header("Sec-Fetch-Mode", "cors")
        .header("Sec-Fetch-Site", "same-origin")
        .send().await?;

    let body = response.text().await?;

    // println!("*** body={}\n\nhangqin\n\n", body);

    let fund: RptF10EhFreeholders = serde_json::from_str(&body)?;

    // println!("{:?}", fund);

    Ok(fund)
}

#[cfg(test)]
mod test {
    use super::*;

    #[tokio::test]
    async fn test_rpt_f10_eh_freeholders() {
        let freeholders = rpt_f10_eh_freeholders(1, 10).await.unwrap();

        let RptF10EhFreeholders { result: RptF10EhFreeholdersResult { data, .. }, .. } =
            freeholders;

        for (idx, item) in data.iter().enumerate() {
            if idx > 3 {
                break;
            }

            println!("[{:00004}] {:?},{:?} ", idx, item.secucode, item.update_date);
        }
    }
}
